/*
 * eren_opcode.c
 *
 *  Created on: 2012-7-12
 *      Author: Steve Liu
 *       Email: eshifang@gmail.com
 *   CopyRight: http://www.eshifang.com
 *
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "php_eren_opcode.h"
#include "eren_opcode_mapping.h"
#include "eren_opcode_function.h"
#include "eren_opcode_compile.h"

static function_entry Functions[] = {
    PHP_FE(eren_show_opcode_file, NULL)
    PHP_FE(eren_show_opcode_string, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry eren_opcode_module_entry = {
    #if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
    #endif
    PHP_EREN_OPCODE_EXTNAME,
    Functions,
    PHP_MINIT(eren_opcode),
    PHP_MSHUTDOWN(eren_opcode),
    PHP_RINIT(eren_opcode),
    PHP_RSHUTDOWN(eren_opcode),
    NULL,
    #if ZEND_MODULE_API_NO >= 20010901
    PHP_EREN_OPCODE_VERSION,
    #endif
    STANDARD_MODULE_PROPERTIES
};

PHP_INI_BEGIN()
PHP_INI_ENTRY("eren_opcode", "0", PHP_INI_ALL, NULL)
PHP_INI_END()

#ifdef COMPILE_DL_EREN_OPCODE
ZEND_GET_MODULE(eren_opcode)
#endif

PHP_MINIT_FUNCTION(eren_opcode)
{
    REGISTER_INI_ENTRIES();

    return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(eren_opcode)
{
    UNREGISTER_INI_ENTRIES();

    return SUCCESS;
}
PHP_RINIT_FUNCTION(eren_opcode)
{
	if(INI_INT("eren_opcode") != 0)
	{
		eren_pre_compile_file = zend_compile_file;
		eren_pre_compile_string = zend_compile_string;
		zend_compile_file = eren_compile_file;
		zend_compile_string = eren_compile_string;
	}

    return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(eren_opcode)
{
	if(INI_INT("eren_opcode") != 0)
	{
		zend_compile_file = eren_pre_compile_file;
		zend_compile_string = eren_pre_compile_string;
	}

    return SUCCESS;
}
PHP_FUNCTION(eren_show_opcode_file)
{
    zend_op_array *op_array = NULL;
    zval *php_file = NULL;
    zval *ret_array = NULL;
    zend_file_handle file;

    if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &php_file) == FAILURE)
    {
        RETURN_FALSE;
    }

    file.type = ZEND_HANDLE_FILENAME;
    file.filename = Z_STRVAL_P(php_file);
    file.free_filename = 0;
    file.opened_path = NULL;

    if(!(op_array = zend_compile_file(&file, ZEND_INCLUDE TSRMLS_CC)))
    {
    	RETURN_FALSE;
    }

    zend_destroy_file_handle(&file TSRMLS_CC);

    ret_array = eren_op_array_to_zval_array(op_array);

    destroy_op_array(op_array TSRMLS_CC);
    efree(op_array);
    op_array = NULL;

    RETVAL_ZVAL(ret_array, NULL, NULL);
}
PHP_FUNCTION(eren_show_opcode_string)
{
	zend_op_array *op_array = NULL;
	char *php_file = NULL;
	int php_file_len = 0;
	zval *z_file = NULL;
	zval *ret_array = NULL;

	if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &php_file, &php_file_len) == FAILURE)
	{
	    RETURN_FALSE;
	}

	MAKE_STD_ZVAL(z_file);
	ZVAL_STRINGL(z_file, php_file, php_file_len, 0);

	if(!(op_array = zend_compile_string(z_file,  "" TSRMLS_CC)))
	{
		RETURN_FALSE;
	}

	zval_ptr_dtor(z_file);

	ret_array = eren_op_array_to_zval_array(op_array);

	destroy_op_array(op_array TSRMLS_CC);
	efree(op_array);
	op_array = NULL;

	RETVAL_ZVAL(ret_array, NULL, NULL);
}
